home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / cips4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-22  |  41.0 KB  |  1,574 lines

  1.  
  2.    /*************************** 
  3.    * 
  4.    *   cips4.c 
  5.    *   COMPOSITE FILE COMPRISING: 
  6.    *   gin.c 
  7.    *   hist.c 
  8.    *   pi.c 
  9.    *   ht.c 
  10.    * 
  11.    ***************************\ 
  12.  
  13.  
  14.  
  15.         /*******************************************************
  16.         *
  17.         *       file d:\cips\gin.c
  18.         *
  19.         *       Functions: This file contains
  20.         *           get_image_name
  21.         *           get_directory_name
  22.         *           extract_base_image_name
  23.         *
  24.         *       Purpose - This function prompts the user to
  25.           *            enter the name of an image.
  26.         *
  27.         *       External Calls:
  28.         *                       clear_buffer
  29.         *
  30.         *       Modifications:
  31.         *           26 September 86 - now uses vision3.h
  32.         *               instead of vision2.h and the read_string
  33.         *               and get_integer instead of  scanf.
  34.         *           11 March 1987 - this function was
  35.         *               removed from the file ip.c and put
  36.         *               in file gin.c.
  37.         *
  38.         ******************************************************/
  39.  
  40.  
  41. #include "cips.h"
  42.  
  43.  
  44.  
  45.  
  46.    /*********************************************
  47.     *
  48.     * get_image_name(...
  49.     *
  50.     * This function reads in the desired image
  51.     * file name.
  52.     *
  53.     *********************************************/
  54.  
  55. get_image_name(name)
  56.    char name[];
  57. {
  58.    char base_name[80],
  59.         dir_name[80],
  60.         new_name[80],
  61.         response[80];
  62.    int  l;
  63.  
  64.    printf("\n\nImage name is--%s\n", name);
  65.    printf("\nDo you want to change:");
  66.    printf("\n (f) file name");
  67.    printf("\n (d) directory name");
  68.    printf("\n (n) no change");
  69.    printf("\n     _\b");
  70.    gets(response);
  71.  
  72.    if((response[0] == 'F') ||
  73.       (response[0] == 'f')){
  74.       printf("\n\nEnter file name (name only no extension)");
  75.       printf("\n--");
  76.       gets(new_name);
  77.       extract_directory_name(name, dir_name);
  78.       sprintf(name, "%s%s.tif", dir_name, new_name);
  79.    }
  80.  
  81.    if((response[0] == 'D') ||
  82.       (response[0] == 'd')){
  83.       printf("\n\nEnter directory name\n--");
  84.       gets(dir_name);
  85.       l = strlen(dir_name);
  86.       if(dir_name[l-1] != 47){
  87.          dir_name[l]   = '/';
  88.          dir_name[l+1] = '\0';
  89.       }
  90.       printf("\n\nEnter file name (name only no extension)");
  91.       printf("\n--");
  92.       gets(new_name);
  93.       sprintf(name, "%s%s.tif", dir_name, new_name);
  94.    }
  95.  
  96. }       /* ends get_image_name  */
  97.  
  98.  
  99.  
  100.  
  101.    /*********************************************
  102.     *
  103.     * extract_directory_name(...
  104.     *
  105.     * This function extracts the sub-directory
  106.     * name out of a file name.
  107.     *
  108.     *********************************************/
  109.  
  110. extract_directory_name(file_name, dir_name)
  111.    char file_name[], dir_name[];
  112. {
  113.    int i, j, k;
  114.  
  115.    i = 1;
  116.    j = 0;
  117.    k = 0;
  118.    while(i){
  119.       if(file_name[k] == 47  ||
  120.          file_name[k] == 92)     j = k;
  121.       if(file_name[k] == '\0')   i = 0;
  122.       k++;
  123.    }
  124.    j++;
  125.    strncpy(dir_name, file_name, j);
  126.    dir_name[j] = '\0';
  127.  
  128. }  /* ends extract_directory_name */
  129.  
  130.  
  131.  
  132.  
  133.  
  134.    /*********************************************
  135.     *
  136.     *   extract_base_image_name(...
  137.     *
  138.     *   This function looks at a full file name
  139.     *   and pulls off the sub-directory name and
  140.     *   the file extension and returns the base
  141.     *   file name.
  142.     *
  143.     *********************************************/
  144.  
  145. extract_base_file_name(file_name, base_name)
  146.    char base_name[], file_name[];
  147. {
  148.    int i, j, k;
  149.    i = 1;
  150.    j = 0;
  151.    k = 0;
  152.    while(i){
  153.       if(file_name[k] == 47  ||
  154.          file_name[k] == 92)     j = k;
  155.       if(file_name[k] == '\0')   i = 0;
  156.       k++;
  157.    }
  158.  
  159.    i = 1;
  160.    k = 0;
  161.    j++;
  162.    while(i){
  163.       if(file_name[j] == '.')
  164.          i = 0;
  165.       else
  166.          base_name[k] = file_name[j];
  167.       j++;
  168.       k++;
  169.    }
  170.    k--;
  171.     base_name[k] = '\0';
  172. printf("\nEBN> base is %s", base_name);
  173. }  /* ends extract_base_file_name */
  174.  
  175.    /**************************************************
  176.    *
  177.    *   file d:\cips\hist.c
  178.    *
  179.    *   Functions: This file contains
  180.    *       calculate_histogram
  181.    *       calculate_histogram
  182.    *       zero_histogram
  183.    *       perform_histogram_equalization
  184.    *       show_histogram
  185.    *       print_histogram
  186.    *       smooth_histogram
  187.    *       display_histogram
  188.    *
  189.    *   Purpose: These functions calculate and display 
  190.    *      the histogram of an input image array.
  191.    *
  192.    *   Modifications:
  193.    *       July 86 - ported to IBM-PC
  194.    *       August 1990 - modified for use in the
  195.    *           C Image Processing System
  196.    *       March 1992 - removed the hardwired values
  197.    *           of 100 and replaced them with ROWS
  198.    *           and COLS.  There are still some
  199.    *           hardwired numbers in this file, but
  200.    *           they deal with displaying a histogram.
  201.    *       October 4, 1992 - added the smooth histogram
  202.    *           function.
  203.    *
  204.    **************************************************/
  205.  
  206.  
  207.  
  208. #define PRINT_WIDTH  80
  209. #define FORMFEED     '\014'
  210.  
  211.  
  212.  
  213.  
  214.           /*****************************************
  215.           *
  216.           *    perform_histogram_equalization(...
  217.           *
  218.           *    This function performs histogram
  219.           *    equalization on the input image array.
  220.           *
  221.           ******************************************/
  222.  
  223. perform_histogram_equalization(image, histogram,
  224.                                new_grays, area)
  225.    float new_grays, area;
  226.    short image[ROWS][COLS];
  227.    unsigned long histogram[];
  228. {
  229.    int i,
  230.        j,
  231.        k;
  232.    unsigned long sum,
  233.             sum_of_h[256];
  234.  
  235.    double constant;
  236.  
  237.    sum = 0;
  238.    for(i=0; i<256; i++){
  239.       sum         = sum + histogram[i];
  240.       sum_of_h[i] = sum;
  241.    }
  242.  
  243.       /* constant = new # of gray levels div by area */
  244.    constant = new_grays/area;
  245.    for(i=0; i<ROWS; i++){
  246.       for(j=0; j<COLS; j++){
  247.          k           = image[i][j];
  248.          image[i][j] = sum_of_h[k] * constant;
  249.       }
  250.    }
  251. }  /* ends perform_histogram_equalization */
  252.  
  253.  
  254.  
  255.  
  256.         /*****************************************
  257.         *
  258.         *   zero_histogram(...
  259.         *
  260.         *   This function clears or zeros a
  261.         *   histogram array.
  262.         *
  263.         ******************************************/
  264.  
  265. zero_histogram(histogram)
  266.    unsigned long histogram[];
  267. {
  268.    int i;
  269.    for(i=0; i<=GRAY_LEVELS; i++)
  270.       histogram[i] = 0;
  271. }  /* ends zero_histogram */
  272.  
  273.  
  274.  
  275.  
  276.         /*****************************************
  277.         *
  278.         *   calculate_histogram(...
  279.         *
  280.         *   This function calculates the histogram
  281.         *   for an input image arry.
  282.         *
  283.         ******************************************/
  284.  
  285. calculate_histogram(image, histogram)
  286.    short  image[ROWS][COLS];
  287.    unsigned long histogram[];
  288. {
  289.    int i,j,k;
  290.    for(i=0; i<ROWS; i++){
  291.       for(j=0; j<COLS; j++){
  292.          k = image[i][j];
  293.          histogram[k] = histogram[k] + 1;
  294.       }
  295.    }
  296. }  /* ends calculate_histogram */
  297.  
  298.  
  299.  
  300.  
  301.         /******************************************
  302.         *
  303.         *   show_histogram(histogram)
  304.         *
  305.         *   This function shows the histogram
  306.         *   on the screen as numbers and stars.
  307.         *
  308.         *******************************************/
  309.  
  310. show_histogram(histogram)
  311.         unsigned long histogram[];
  312. {
  313.         int     count,
  314.                 i,
  315.                 j;
  316.         unsigned long max, scale;
  317.  
  318.  
  319.         max   = 0;
  320.         count = 0;
  321.  
  322.         for(i=0; i<GRAY_LEVELS; i++)
  323.            if(histogram[i] > max)
  324.               max = histogram[i];
  325.  
  326.         if(max > (70 - 12))
  327.            scale = max/(70 - 12);
  328.         else
  329.            scale = 1;
  330.  
  331.         printf("\n max=%ld scale=%ld",max, scale);
  332.  
  333.         printf("\n\ngray    count");
  334.         printf("\nlevel");
  335.  
  336.         for(i=0; i<256; i++){
  337.            if(histogram[i] == 0)
  338.               ++count;
  339.            else
  340.               count = 0;
  341.  
  342.            if(count < 2){
  343.               printf("\n %4d: %7ld",i,histogram[i]);
  344.               for(j=0; j<((int)(histogram[i]/scale));
  345.                   j++){
  346.                  printf("*");
  347.               }   /* ends loop over j             */
  348.            }      /* ends if count < 5            */
  349.         }         /* ends loop over i GRAY_LEVELS */
  350. }       /* ends show_histogram */
  351.  
  352.  
  353.  
  354.         /*********************************************
  355.         *
  356.         *   print_histogram(histogram)
  357.         *
  358.         *   This function prints the histogram
  359.         *   input to the function.
  360.         *
  361.         **********************************************/
  362.  
  363. print_histogram(histogram, name)
  364.         char name[];
  365.         unsigned long histogram[];
  366. {
  367.         char    string[300],
  368.                 output[300];
  369.  
  370.         int     count,
  371.                 i,
  372.                 j,
  373.                 line_counter,
  374.                 print_counter;
  375.         unsigned long scale, max;
  376.  
  377.         FILE *printer;
  378.  
  379.         if( (printer = fopen("prn", "w")) == NULL)
  380.            printf("\nPH> Could not open printer");
  381.         else
  382.            printf("\nPH> The print file is opened");
  383.  
  384.         max           = 0;
  385.         count         = 0;
  386.         print_counter = 0;
  387.  
  388.         for(i=0; i<256; i++)
  389.            if(histogram[i] > max)
  390.               max = histogram[i];
  391.  
  392.         if(max > (PRINT_WIDTH - 12))
  393.            scale = max/(PRINT_WIDTH - 12);
  394.         else
  395.            scale = 1;
  396.  
  397.         printf("\n max=%ld scale=%ld",max, scale);
  398.  
  399.         printf("\nPI> Print header");
  400.         line_counter = 0;
  401.         hist_long_clear_buffer(string);
  402.         sprintf(string, 
  403.            "          This image is -- %s --\n", 
  404.            name);
  405.         fputs(string, printer);
  406.         ++line_counter;
  407.  
  408.         hist_long_clear_buffer(string);
  409.         sprintf(string, " \n");
  410.         fputs(string, printer);
  411.         ++line_counter;
  412.  
  413.         hist_long_clear_buffer(string);
  414.         sprintf(string, "          gray    count\n");
  415.         fputs(string, printer);
  416.         ++line_counter;
  417.         hist_long_clear_buffer(string);
  418.         sprintf(string, "          level\n");
  419.         fputs(string, printer);
  420.         ++line_counter;
  421.  
  422.         for(i=0; i<256; i++){
  423.            if(histogram[i] == 0)
  424.               ++count;
  425.            else
  426.               count = 0;
  427.  
  428.            if(count < 2){
  429.               printf(" %4d: %7ld",i,histogram[i]);
  430.               print_counter++;
  431.               if(print_counter >= 6){
  432.                  printf("\n");
  433.                  print_counter = 0;
  434.               }  /* ends if print_counter >= 6 */
  435.  
  436.               hist_long_clear_buffer(string);
  437.               sprintf(string,
  438.                 "           %3d: %7ld ->",
  439.                 i,histogram[i]);
  440.               fputs(string, printer);
  441.               hist_long_clear_buffer(string);
  442.               sprintf(output, " ");
  443.               for(j=0; j<((int)(histogram[i]/scale)); 
  444.                   j++){
  445.                  sprintf(string, "*");
  446.                  strcat(output, string);
  447.               }         /* ends loop over j */
  448.               fputs(string, printer); 
  449.               fputc('\n', printer);
  450.               ++line_counter;
  451.               if(line_counter >= 55){
  452.                  line_counter = 0;
  453.                  putc(FORMFEED, printer);
  454.               }  /* ends if line_counter >=55  */
  455.            }  /* ends if count < 2 */
  456.         }  /* ends loop over i */
  457.         putc(FORMFEED, printer);
  458.         fclose(printer);
  459.  
  460. }        /* ends print_histogram */
  461.  
  462.  
  463.  
  464.  
  465.         /*******************************************
  466.         *
  467.         *   display_histogram(histogram)
  468.         *
  469.         *   This function shows the histogram
  470.         *   input to the function.
  471.         *
  472.         ********************************************/
  473.  
  474. display_histogram(histogram, x, y,
  475.                   line_color, data_color)
  476.         int data_color, line_color, x, y;
  477.         unsigned long histogram[];
  478. {
  479.         int     count,
  480.                 i,
  481.                 j,
  482.                 length;
  483.         unsigned long scale, max;
  484.  
  485.         max   = 0;
  486.         count = 0;
  487.  
  488.         for(i=0; i<256; i++)
  489.            if(histogram[i] > max)
  490.               max = histogram[i];
  491.  
  492.         if(max > (200 - 12))
  493.            scale = max/(100 - 25);
  494.         else
  495.            scale = 1;
  496.  
  497.    /***************************
  498.    *
  499.    *   clear out an area for
  500.    *   this histogram display
  501.    *
  502.    ****************************/
  503.  
  504.         my_setcolor(line_color);
  505.         for(i=0; i<258; i++){
  506.            for(j=0; j<100; j++){
  507.               my_setpixel(x-1+i, y-j);
  508.            }
  509.         }
  510.  
  511.  
  512.          /***************************
  513.          *
  514.          *  draw the histogram axes
  515.          *
  516.          ****************************/
  517.  
  518.         my_setcolor(0);
  519.  
  520.         my_moveto(x, y);
  521.         my_lineto(x+255, y);
  522.         my_moveto(x, y);
  523.         my_lineto(x, y-95);
  524.         my_moveto(x+50, y);
  525.         my_lineto(x+50, y-95);
  526.         my_moveto(x+100, y);
  527.         my_lineto(x+100, y-95);
  528.         my_moveto(x+150, y);
  529.         my_lineto(x+150, y-95);
  530.         my_moveto(x+200, y);
  531.         my_lineto(x+200, y-95);
  532.         my_moveto(x+255, y);
  533.         my_lineto(x+255, y-95);
  534.  
  535.          /***************************
  536.          *
  537.          *  loop thru the histogram
  538.          *  and plot the scaled data
  539.          *
  540.          ****************************/
  541.  
  542.         my_setlinestyle(0xFFFF);
  543.         my_setcolor(data_color);
  544.  
  545.         for(i=0; i<256; i++){
  546.            if(histogram[i] != 0){
  547.               length = histogram[i]/scale;
  548.               my_moveto(x+i, y);
  549.               my_lineto(x+i, y-length);
  550.            }
  551.         }  /* ends loop over i GRAY_LEVELS */
  552. }  /* ends display_histogram */
  553.  
  554.  
  555.  
  556.  
  557.        /*****************************************
  558.        *
  559.        *   display_menu_for_histogram(...
  560.        *
  561.        *   This function shows the options
  562.        *   available for histogram function.
  563.        *
  564.        ****************************************/
  565.  
  566. display_menu_for_histogram(print, vertical, 
  567.                            horizontal)
  568.    int *print, *vertical, *horizontal;
  569. {
  570.    char response[80];
  571.    int  int_response, not_finished, r;
  572.  
  573.    not_finished = 1;
  574.    while(not_finished){
  575.       printf(
  576.       "\n\nHISTOGRAM> Enter choice (0 for no change)");
  577.       printf(
  578.       "\nHISTOGRAM> 1. print is %d (1=print 0=display)",
  579.          *print);
  580.       printf(
  581.       "\nHISTOGRAM> 2. # of vertical %dx%d areas %d",
  582.          ROWS, COLS, *vertical);
  583.       printf(
  584.       "\nHISTOGRAM> 3. # of horizontal %dx%d areas %d",
  585.          ROWS,COLS,*horizontal);
  586.       printf("\nHISTOGRAM> _\b");
  587.       get_integer(&r);
  588.  
  589.       if(r == 0)
  590.          not_finished = 0;
  591.  
  592.  
  593.       if(r == 1){
  594.          printf(
  595.             "\nHISTOGRAM> Enter 1 for print or 0 for display");
  596.          printf("\nHISTOGRAM> ___");
  597.          get_integer(&int_response);
  598.          *print = int_response;
  599.       }  /* ends if r == 1 */
  600.  
  601.       if(r == 2){
  602.       printf(
  603.      "\nHISTOGRAM> Enter # of vertical %dx%d areas ",
  604.             ROWS,COLS);
  605.          printf("\nHISTOGRAM> _\b");
  606.          get_integer(&int_response);
  607.          *vertical = int_response;
  608.       }  /* ends if r == 2  */
  609.  
  610.       if(r == 3){
  611.          printf(
  612.      "\nHISTOGRAM> Enter # of horizontal %dx%d areas ",
  613.           ROWS,COLS);
  614.          printf("\nHISTOGRAM> ___");
  615.          get_integer(&int_response);
  616.          *horizontal = int_response;
  617.       }  /* ends if r == 3 */
  618.  
  619.    }  /* ends while not_finished  */
  620. }  /* ends display_menu  */
  621.  
  622.  
  623.  
  624.  
  625.       /********************************************
  626.       *
  627.       *   calculate_area_histogram(...
  628.       *
  629.       *   This function calculates the histogram
  630.       *   for several ROWSxCOLS arrays of an
  631.       *   image.  The user inputs the number
  632.       *   of vertical and horizontal ROWSxCOLS
  633.       *   arrays to be histogramed.  This function
  634.       *   uses the image file name to read the image
  635.       *   arrays and calculate the overall
  636.       *   histogram.
  637.       *
  638.       *********************************************/
  639.  
  640. calculate_area_histogram(histogram, vertical, 
  641.                    horizontal, the_image, name, il, 
  642.                    ie, ll, le)
  643.    char     name[];
  644.    int      horizontal, il, ie, ll, le, vertical;
  645.    short    the_image[ROWS][COLS];
  646.    unsigned long histogram[];
  647. {
  648.    int count, i, j;
  649.  
  650.    printf("\nCalculating histograms");
  651.    zero_histogram(histogram);
  652.    count = 1;
  653.  
  654.    for(i=0; i<vertical; i++){
  655.       for(j=0; j<horizontal; j++){
  656.          printf("\n\tcalculating %d of %d",
  657.                count, horizontal*vertical);
  658.          read_tiff_image(name, the_image,
  659.                il+i*ROWS, ie+j*COLS, 
  660.                ll+i*ROWS, le+j*COLS);
  661.          calculate_histogram(the_image, histogram);
  662.          count++;
  663.       }  /* ends loop over j */
  664.    }  /* ends loop over i */
  665.  
  666. }  /* calcualte_area_histogram */
  667.  
  668.  
  669.  
  670.       /********************************************
  671.       *
  672.       *   smooth_histogram(...
  673.       *
  674.       *   This function smoothes the input histogram
  675.       *   and returns it.  It uses a simple averaging
  676.       *   scheme where each point in the histogram
  677.       *   is replaced by the average of itself and
  678.       *   the two points on either side of it.
  679.       *
  680.       *********************************************/
  681.  
  682. smooth_histogram(histogram)
  683.    unsigned long histogram[];
  684. {
  685.    int i;
  686.    unsigned long new_hist[GRAY_LEVELS+1];
  687.  
  688.    zero_histogram(new_hist);
  689.  
  690.    new_hist[0] = (histogram[0] + histogram[1])/2;
  691.    new_hist[GRAY_LEVELS] =
  692.       (histogram[GRAY_LEVELS] +
  693.        histogram[GRAY_LEVELS-1])/2;
  694.  
  695.    for(i=1; i<GRAY_LEVELS; i++){
  696.       new_hist[i] = (histogram[i-1] +
  697.                      histogram[i]   +
  698.                      histogram[i+1])/3;
  699.    }
  700.  
  701.    for(i=0; i<=GRAY_LEVELS; i++)
  702.       histogram[i] = new_hist[i];
  703.  
  704. }  /* ends smooth_histogram */
  705.  
  706.  
  707.  
  708. hist_long_clear_buffer(string)
  709.    char string[];
  710. {
  711.    int i;
  712.    for(i=0; i<300; i++)
  713.       string[i] = ' ';
  714. }
  715.  
  716.  
  717.    /**************************************************
  718.    *
  719.    *   file d:\cips\pi.c
  720.    *
  721.    *   Functions: This file contains
  722.    *       print_image
  723.    *       print_image_array
  724.    *       perform_printing
  725.    *       print_column_header
  726.    *
  727.    *   Purpose - These functions print an image out 
  728.    *       to the line printer.  The parameters in 
  729.    *       this function are defined differently 
  730.    *       than in most other CIPS functions.  
  731.    *       The parameters il, ie, ll, le are 
  732.    *       coordinates inside the 100x100 image array.
  733.    *       The parameters first_line and first_element
  734.    *       are coordinates for the entire image file.
  735.    *       So, if you want to start printing at row 10
  736.    *       and column 10 of the image file you would 
  737.    *       call:
  738.    *
  739.    *       read_tiff_image(name, the_image, 10, 10,
  740.    *                       110, 110);
  741.    *       print_image(the_image, name, 1, 1, 1, 
  742.    *                   100, 18, 10, 10);
  743.    *
  744.    *       In normal print mode you can only print 17
  745.    *       columns.
  746.    *       le - ie = 17.
  747.    *
  748.    *
  749.    *   External Calls:
  750.    *       none
  751.    *
  752.    *   Modifications:
  753.    *       6 January 1987 - created
  754.    *       14 August 1990 - modified to be part of the
  755.    *           C Image Processing System
  756.    *       14 June 1993 - removed calls to
  757.    *           my_fwrite my_fwriteln
  758.    *
  759.    **************************************************/
  760.  
  761. #define  FORMFEED  '\014'
  762.  
  763.    /*********************************************
  764.    *
  765.    *   printf_image(...
  766.    *
  767.    *********************************************/
  768.  
  769. print_image(the_image, name, channel, il, ie, ll, le,
  770.             first_line, first_element)
  771.    char  name[];
  772.    int   channel, il, ie, ll, le, 
  773.          first_line, first_element;
  774.    short the_image[ROWS][COLS];
  775. {
  776.    char printer_name[MAX_NAME_LENGTH];
  777.    FILE *printer;
  778.  
  779.    strcpy(printer_name, "prn");
  780.    if( (printer = fopen(printer_name, "w")) == NULL)
  781.       printf("\nPI> Could not open printer");
  782.    else{
  783.       printf("\nPI> The print file is opened");
  784.  
  785.            /*****************************************
  786.            *
  787.            *   If your printer has some form of
  788.            *   condensed printing, you can send those
  789.            *   commands via software using the fputc
  790.            *   function.  For example, if your printer
  791.            *   needs to sequence X Y Z to start
  792.            *   condensed printing, insert the following
  793.            *   three calls right here:
  794.            *   fputc('X', printer);
  795.            *   fputc('Y', printer);
  796.            *   fputc('Z', printer);
  797.            *
  798.            ******************************************/
  799.  
  800.       perform_printing(printer, the_image, name, 
  801.                        channel, il, ll, ie, le, 
  802.                        first_line, first_element);
  803.       fclose(printer);
  804.    }  /* ends else print  */
  805. }     /* ends print_image  */
  806.  
  807.  
  808.  
  809.  
  810.    /*********************************************
  811.    *
  812.    *   perform_printing(...
  813.    *
  814.    *********************************************/
  815.  
  816. perform_printing(printer, the_image, name, channel,
  817.                  il, ll, ie, le, first_line, 
  818.                  first_element)
  819.    char  name[];
  820.    FILE  *printer;
  821.    int   channel, il, ie, ll, le, 
  822.          first_line, first_element;
  823.    short the_image[ROWS][COLS];
  824. {
  825.    char output[3*COLS],
  826.         response[80],
  827.         string[3*COLS];
  828.    int  i,
  829.         j,
  830.         k,
  831.         line_counter;
  832.  
  833.  
  834.    printf("\nPI> Print header");
  835.    line_counter = 0;
  836.    pi_long_clear_buffer(string);
  837.    sprintf(string, "     This image is -- %s --\n", 
  838.            name);
  839.    fputs(string, printer);
  840.    ++line_counter;
  841.  
  842.    pi_long_clear_buffer(string);
  843.    sprintf(string, "     The parameters are:\n");
  844.    fputs(string, printer);
  845.    ++line_counter;
  846.  
  847.    pi_long_clear_buffer(string);
  848.    sprintf(string, 
  849.            "     channel=%d il=%d ll=%d ie=%d le=%d\n",
  850.            channel, first_line, first_line+ll-2,
  851.            first_element, first_element+le-2);
  852.    fputs(string, printer);
  853.    ++line_counter;
  854.  
  855.    pi_long_clear_buffer(string);
  856.    sprintf(string, " \n");
  857.    fputs(string, printer);
  858.    ++line_counter;
  859.  
  860.    print_column_header(&line_counter, first_element, 
  861.                        ie, le, output, string, 
  862.                        printer);
  863.  
  864.    for(i=il; i<ll; i++){
  865.  
  866.       pi_long_clear_buffer(string);
  867.  
  868.         /* now print the image  */
  869.       sprintf(string, "      ");
  870.       pi_long_clear_buffer(output);
  871.       sprintf(output, "%3d-", i+first_line-1);
  872.       strcat(string, output);
  873.       for(j=ie; j<le; j++){
  874.          pi_long_clear_buffer(output);
  875.          sprintf(output,"%4d",the_image[i][j]);
  876.          strcat(string, output);
  877.       }  /* ends loop over j columns */
  878.  
  879.       fputs(string, printer); fputc('\n', printer);
  880.       line_counter = line_counter + 1;
  881.       if(line_counter >= 53){
  882.          line_counter = 0;
  883.          putc(FORMFEED, printer);
  884.          print_column_header(&line_counter, 
  885.                              first_element, ie,
  886.                              le, output, string, 
  887.                              printer);
  888.       }  /* ends if line_counter >=65  */
  889.    }  /* ends loop over i rows */
  890.  
  891.    for(i=line_counter; i<66; i++){
  892.       pi_long_clear_buffer(string);
  893.       sprintf(string, " \n");
  894.       fputs(string, printer);
  895.    }
  896.  
  897. }     /* ends perform_printing  */
  898.  
  899.  
  900.  
  901.  
  902.    /*********************************************
  903.    *
  904.    *   print_column_header(...
  905.    *
  906.    *********************************************/
  907.  
  908. print_column_header(line_counter, first_element, 
  909.                     ie, le, output,
  910.                     string, printer)
  911.    char string[], output[];
  912.    FILE *printer;
  913.    int  first_element, ie, le, *line_counter;
  914. {
  915.    int k;
  916.  
  917.    pi_long_clear_buffer(string);
  918.    sprintf(string, "          ");
  919.  
  920.  
  921.    for(k=first_element;k<(first_element+(le-ie));k++){
  922.       pi_long_clear_buffer(output);
  923.       sprintf(output, "-%3d", k);
  924.       strcat(string, output);
  925.    }  /* ends loop over k  */
  926.    fputs(string, printer); fputc('\n', printer);
  927.    *line_counter = *line_counter + 1;
  928. }  /* ends print_column_header  */
  929.  
  930.  
  931.  
  932.  
  933.    /*************************************************
  934.    *
  935.    *   print_image_array(...
  936.    *
  937.    *   This function prints a 100x100 image array.
  938.    *
  939.    **************************************************/
  940.  
  941. print_image_array(the_image)
  942.    short the_image[ROWS][COLS];
  943. {
  944.    char response[80];
  945.    printf("\nPIA> Enter a comment line\n--");
  946.    gets(response);
  947.                                 /*     il  ie  ll    le    */
  948.    print_image(the_image, response, 0,  1,  1, 100,  17, 0, 0);
  949.    print_image(the_image, response, 0,  1, 18, 100,  35, 0, 0);
  950.    print_image(the_image, response, 0,  1, 36, 100,  53, 0, 0);
  951.    print_image(the_image, response, 0,  1, 54, 100,  71, 0, 0);
  952.    print_image(the_image, response, 0,  1, 72, 100,  89, 0, 0);
  953.    print_image(the_image, response, 0,  1, 90, 100, 100, 0, 0);
  954.  
  955. }  /* ends print_image_array  */
  956.  
  957.  
  958.  
  959.  
  960.    /*********************************************
  961.    *
  962.    *   pi_long_clear_string(...
  963.    *
  964.    *********************************************/
  965.  
  966. pi_long_clear_buffer(string)
  967.    char string[];
  968. {
  969.    int i;
  970.    for(i=0; i<300; i++)
  971.       string[i] = ' ';
  972. }
  973.  
  974.  
  975.    /**************************************************
  976.    *
  977.    *   file d:\cips\ht.c
  978.    *
  979.    *   Functions: This file contains
  980.    *       display_using_halftoning
  981.    *       half_tone
  982.    *       show_half_tone
  983.    *       get_threshold_value
  984.    *
  985.    *   Purpose: This program displays an image using 
  986.    *      a halftoning process.  The algorithm was 
  987.    *      taken from "Personal computer based image 
  988.    *      processing with halftoning," John A Saghri, 
  989.    *      Hsieh S. Hou, Andrew Tescher, Optical 
  990.    *      Engineering, March 1986, Vol.25, No. 3, 
  991.    *      pp 499-503. The display_using_halftoning
  992.    *      determines display size and reads the image.
  993.    *      The half_tone function implements the 
  994.    *      algorithm shown on page 502 of the article.
  995.    *
  996.    *      The function print_halftone_array prints 
  997.    *      a half toned image array to a regular line 
  998.    *      printer.
  999.    *
  1000.    *
  1001.    *   External Calls:
  1002.    *      rtiff.c - read_tiff_image
  1003.    *      numcvrt.c - get_integer
  1004.    *
  1005.    *   Modifications:
  1006.    *      30 September 86 - created
  1007.    *      18 August 1990 - modified for use in the
  1008.    *          C Image Processing System.
  1009.    *
  1010.    *
  1011.    **************************************************/
  1012.  
  1013.  
  1014.  
  1015. #define  FORMFEED  '\014'
  1016.  
  1017. float eg[ROWS][COLS], ep[ROWS][COLS];
  1018.  
  1019. display_using_halftoning(in_image, file_name,
  1020.          il, ie, ll, le, threshold, invert,
  1021.          image_colors, image_header, monitor_type,
  1022.          print, show_hist, color_transform)
  1023.  
  1024.    char  color_transform[], file_name[], 
  1025.          monitor_type[];
  1026.    int   image_colors, invert,
  1027.          il, ie, ll, le, threshold,
  1028.          print, show_hist;
  1029.    short in_image[ROWS][COLS];
  1030.    struct tiff_header_struct *image_header;
  1031.  
  1032. {
  1033.    char response[80];
  1034.  
  1035.    int  a,
  1036.         b,
  1037.         channel,
  1038.         color,
  1039.         count,
  1040.         data_color,
  1041.         display_mode,
  1042.         horizontal,
  1043.         i,
  1044.         j,
  1045.         k,
  1046.         l,
  1047.         line_color,
  1048.         max_horizontal,
  1049.         max_vertical,
  1050.         not_finished,
  1051.         one,
  1052.         vertical,
  1053.         x,
  1054.         x_offset,
  1055.         y,
  1056.         y_offset,
  1057.         zero;
  1058.  
  1059.    float area, new_grays;
  1060.  
  1061.    unsigned long histogram[256], new_hist[256];
  1062.  
  1063.  
  1064.        if(  (show_hist == 1)  &&
  1065.             (color_transform[0] != 'H'))
  1066.           zero_histogram(histogram);
  1067.  
  1068.          /*******************************************
  1069.          *
  1070.          *   Use the monitor type to set the vertical
  1071.          *   horizontal and display_mode parameters.
  1072.          *   Also set the values for one and zero.
  1073.          *   one and zero will vary depending on the
  1074.          *   monitor type.
  1075.          *
  1076.          ********************************************/
  1077.  
  1078.  
  1079.       if(  (monitor_type[0] == 'M')  ||
  1080.            (monitor_type[0] == 'm')){
  1081.          vertical     = 3;
  1082.          horizontal   = 2;
  1083.          display_mode = HRESBW;
  1084.          one          = 1;
  1085.          zero         = 0;
  1086.       }
  1087.  
  1088.       if(  (monitor_type[0] == 'C')  ||
  1089.            (monitor_type[0] == 'c')){
  1090.          vertical     = 3;
  1091.          horizontal   = 2;
  1092.          display_mode = MRES4COLOR;
  1093.          one          = 3;
  1094.          zero         = 1;
  1095.       }
  1096.  
  1097.       if(  (monitor_type[0] == 'V')  ||
  1098.            (monitor_type[0] == 'v')){
  1099.          vertical     = 6;
  1100.          horizontal   = 4;
  1101.          display_mode = VRES16COLOR;
  1102.          one          = 5;
  1103.          zero         = 1;
  1104.       }
  1105.  
  1106.       if(  (monitor_type[0] == 'E')  ||
  1107.            (monitor_type[0] == 'e')){
  1108.          vertical     = 6;
  1109.          horizontal   = 3;
  1110.          display_mode = ERESCOLOR;
  1111.          one          = 5;
  1112.          zero         = 1;
  1113.       }
  1114.  
  1115.       max_horizontal = (image_header->image_length+50)
  1116.                          /COLS;
  1117.       max_vertical   = (image_header->image_width+50)
  1118.                          /ROWS;
  1119.  
  1120.       if(horizontal > max_horizontal) 
  1121.             horizontal = max_horizontal;
  1122.       if(vertical > max_vertical) 
  1123.             vertical = max_vertical;
  1124.  
  1125.       if(print == 1){
  1126.          vertical   = 1;
  1127.          horizontal = 1;
  1128.       }
  1129.  
  1130.  
  1131.  
  1132.         /****************************************
  1133.         *
  1134.         *   If color transform wants histogram
  1135.         *   equalization, then read in the
  1136.         *   image arrays and calculate the
  1137.         *   histogram.   Zero both the histogram
  1138.         *   and the new_hist.  You will need the
  1139.         *   new_hist if you want to display the
  1140.         *   equalized hist.
  1141.         *
  1142.         *****************************************/
  1143.  
  1144.       if(color_transform[0] == 'H'){
  1145.          count = 1;
  1146.          zero_histogram(histogram);
  1147.          zero_histogram(new_hist);
  1148.          for(a=0; a<vertical; a++){
  1149.             for(b=0; b<horizontal; b++){
  1150.  
  1151.                x = a*COLS;
  1152.                y = b*ROWS;
  1153.  
  1154.                printf("\nHT> Calculating histogram");
  1155.                printf(" %d of %d",
  1156.                       count,vertical*horizontal);
  1157.                count++;
  1158.  
  1159.                read_tiff_image(file_name, in_image, 
  1160.                             il+y, ie+x, ll+y, le+x);
  1161.                calculate_histogram(in_image, 
  1162.                                    histogram);
  1163.  
  1164.             }  /* ends loop over b */
  1165.          }  /* ends loop over a */
  1166.       }  /* ends if display_mode == H */
  1167.  
  1168.  
  1169.  
  1170.  
  1171.            /* set graphics mode */
  1172.       if(print == 0)
  1173.          my_setvideomode(display_mode); /* MSC 6.0 */
  1174.       else{
  1175.          printf("\n\nHT> Calculating for printing ");
  1176.          printf("\nHT> Counting from 0 to 99\n");
  1177.       }
  1178.  
  1179.         /********************************************
  1180.         *
  1181.         *   Loop over horizontal and vertical. Read
  1182.         *   the image array and display it after
  1183.         *   calculating the half tone values.
  1184.         *
  1185.         *
  1186.         *   If you want to show the histogram AND
  1187.         *   do not want to do hist equalization
  1188.         *   then calculate the hist from the
  1189.         *   original image array.
  1190.         *
  1191.         *   If you want to do hist equalization
  1192.         *   then calculate the new_hist AFTER
  1193.         *   the image has been equalized.
  1194.         *
  1195.         *   We will equalize the histogram down
  1196.         *   to half the original shades of gray
  1197.         *   and will cut the threshold in half.
  1198.         *
  1199.         *****************************************/
  1200.  
  1201.  
  1202.  
  1203.       for(i=0; i<horizontal; i++){
  1204.          for(j=0; j<vertical; j++){
  1205.             read_tiff_image(file_name, in_image, 
  1206.                            il+i*ROWS, ie+j*COLS, 
  1207.                            ll+i*ROWS, le+j*COLS);
  1208.  
  1209.             if(   (show_hist == 1)  &&
  1210.                   (color_transform[0] != 'H'))
  1211.                calculate_histogram(in_image, histogram);
  1212.  
  1213.             if(color_transform[0] == 'H'){
  1214.  
  1215.                area = ((long)(vertical))*
  1216.                       ((long)(horizontal));
  1217.                area = area*10000.0;
  1218.                new_grays = image_colors/2;
  1219.  
  1220.                perform_histogram_equalization(in_image,
  1221.                         histogram, new_grays, area);
  1222.  
  1223.                calculate_histogram(in_image, new_hist);
  1224.  
  1225.             }  /* ends if color_transform == S */
  1226.  
  1227.             if(color_transform[0] == 'H')
  1228.                half_tone(in_image, threshold/2, 
  1229.                       eg, ep, i, j,
  1230.                       one, zero, invert, print);
  1231.  
  1232.             else
  1233.                half_tone(in_image, threshold, 
  1234.                       eg, ep, i, j,
  1235.                       one, zero, invert, print);
  1236.  
  1237.          }  /* ends loop over j */
  1238.       }  /*  ends loop over i */
  1239.  
  1240.  
  1241.  
  1242.          /***************************
  1243.          *
  1244.          *   if show_hist == 1 then
  1245.          *   display the histogram
  1246.          *   in the lower right hand
  1247.          *   corner of screen
  1248.          *
  1249.          ****************************/
  1250.  
  1251.       if(  (show_hist == 1)   &&
  1252.            (print == 0)){
  1253.  
  1254.          if(monitor_type[0] == 'V'){
  1255.             y_offset   = 470;
  1256.             x_offset   = 380;
  1257.             line_color = 3;
  1258.             data_color = 8;
  1259.          }
  1260.  
  1261.          if(monitor_type[0] == 'E'){
  1262.             y_offset   = 310;
  1263.             x_offset   = 380;
  1264.             line_color = 3;
  1265.             data_color = 8;
  1266.          }
  1267.  
  1268.          if(monitor_type[0] == 'M'){
  1269.             y_offset   = 190;
  1270.             x_offset   = 60;
  1271.             line_color = 1;
  1272.             data_color = 1;
  1273.          }
  1274.  
  1275.          if(monitor_type[0] == 'C'){
  1276.             y_offset   = 190;
  1277.             x_offset   = 60;
  1278.             line_color = 1;
  1279.             data_color = 3;
  1280.          }
  1281.  
  1282.          if(color_transform[0] == 'S')
  1283.             display_histogram(histogram, x_offset,
  1284.                    y_offset, line_color, data_color);
  1285.  
  1286.          if(color_transform[0] == 'H')
  1287.             display_histogram(new_hist, x_offset,
  1288.                    y_offset, line_color, data_color);
  1289.  
  1290.       }  /* ends if show_hist == 1 and print == 0 */
  1291.  
  1292.  
  1293.  
  1294.       if(print == 1) 
  1295.          printf("\n\nHT> Hit ENTER to continue");
  1296.       gets(response);
  1297.       my_clear_text_screen();
  1298.  
  1299. }  /* ends main  */
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.        /*********************************************
  1306.        *
  1307.        *   half_tone(...
  1308.        *
  1309.        *   ep[m][n] = sum of erros propogated
  1310.        *               to position (m,n).
  1311.        *   eg[m][n] = total error generated at
  1312.        *               location (m,n).
  1313.        *
  1314.        **********************************************/
  1315.  
  1316. half_tone(in_image, threshold, eg, ep, yoff,
  1317.            xoff, one, zero, invert, print)
  1318.    int   invert, threshold, xoff, yoff,
  1319.          one, print, zero;
  1320.    float eg[ROWS][COLS], ep[ROWS][COLS];
  1321.    short in_image[ROWS][COLS];
  1322. {
  1323.    float c[2][3],
  1324.          sum_p,
  1325.          t,
  1326.          tt;
  1327.    int   color, count, i, j, m, n;
  1328.    short srow, scol;
  1329.  
  1330.    c[0][0] = 0.0;
  1331.    c[0][1] = 0.2;
  1332.    c[0][2] = 0.0;
  1333.    c[1][0] = 0.6;
  1334.    c[1][1] = 0.1;
  1335.    c[1][2] = 0.1;
  1336.    count   =   0;
  1337.  
  1338.       /***********************************************
  1339.       *
  1340.       *   Calculate the total propogated error
  1341.       *   at location(m,n) due to prior
  1342.       *   assignment.
  1343.       *
  1344.       *   Go through the input image.  If the output
  1345.       *   should be one then display that pixel as such.
  1346.       *   If the output should be zero then display it
  1347.       *   that way.
  1348.       *
  1349.       *   Also set the pixels in the input image array
  1350.       *   to 1's and 0's in case the print option
  1351.       *   was chosen.
  1352.       *
  1353.       ************************************************/
  1354.  
  1355.    for(i=0; i<ROWS; i++){
  1356.       for(j=0; j<COLS; j++){
  1357.          eg[i][j] = 0.0;
  1358.          ep[i][j] = 0.0;
  1359.       }
  1360.    }
  1361.  
  1362.        /**********************************************
  1363.        *
  1364.        *   29 February 1988 - Fix to remove a solid 
  1365.        *   line at the bottom of each region. Loop 
  1366.        *   over ROWS-1 and then draw an extra line.
  1367.        *
  1368.        **********************************************/
  1369.  
  1370.    for(m=0; m<ROWS-1; m++){
  1371.       for(n=0; n<COLS; n++){
  1372.  
  1373.          sum_p = 0.0;
  1374.          for(i=0; i<2; i++){
  1375.             for(j=0; j<3; j++){
  1376.                sum_p = sum_p + 
  1377.                        c[i][j] * eg[m-i+1][n-j+1];
  1378.             }  /* ends loop over j */
  1379.          }     /* ends loop over i */
  1380.  
  1381.          ep[m][n] = sum_p;
  1382.          t = in_image[m][n] + ep[m][n];
  1383.          tt = t;
  1384.  
  1385.                /**********************************
  1386.                *
  1387.                *    Here set the point [m][n]=one
  1388.                *
  1389.                ***********************************/
  1390.  
  1391.          if(t > threshold){
  1392.             eg[m][n] = t - threshold*2;
  1393.             ++count;
  1394.             color = one;
  1395.             if(invert == 1) color = zero;
  1396.  
  1397.             scol = (short)(n + xoff*COLS);
  1398.             srow = (short)(m + yoff*ROWS);
  1399.  
  1400.             if(invert == 1)
  1401.                in_image[m][n] = 1;
  1402.             else
  1403.                in_image[m][n] = 0;
  1404.  
  1405.             if(print == 0){
  1406.                my_setcolor(color);      /* MSC 6.0 */
  1407.                my_setpixel(scol, srow); /* MSC 6.0 */
  1408.             }  /* ends if print == 0 */
  1409.          }  /* ends if t > threshold  */
  1410.  
  1411.  
  1412.                /**********************************
  1413.                *
  1414.                *    Here set the point [m][n]=zero
  1415.                *
  1416.                ***********************************/
  1417.  
  1418.          else{
  1419.             eg[m][n] = t;
  1420.             color = zero;
  1421.             if(invert == 1) color = one;
  1422.  
  1423.             scol = (short)(n + xoff*COLS);
  1424.             srow = (short)(m + yoff*ROWS);
  1425.  
  1426.             if(invert == 1)
  1427.                in_image[m][n] = 0;
  1428.             else
  1429.                in_image[m][n] = 1;
  1430.  
  1431.             if(print == 0){
  1432.                my_setcolor(color);      /* MSC 6.0 */
  1433.                my_setpixel(scol, srow); /* MSC 6.0 */
  1434.             } /* ends if print == 0 */
  1435.  
  1436.          }  /* ends else t <= threshold  */
  1437.  
  1438.       }  /* ends loop over n columns */
  1439.  
  1440.       if(print == 1) printf("%3d", m);
  1441.  
  1442.    }         /* ends loop over m rows */
  1443.  
  1444.  
  1445.       /* Now display an extra line if print is 0 */
  1446.    if(print == 0){
  1447.       for(j=0; j<COLS; j++){
  1448.  
  1449.         if(in_image[ROWS-2][j] == 1)
  1450.            color = zero;
  1451.         else
  1452.            color = one;
  1453.  
  1454.         if(invert == 1){
  1455.             if(in_image[ROWS-2][j] == 1)
  1456.                color = zero;
  1457.             else
  1458.                color = one;
  1459.         }  /* ends if invert == 1 */
  1460.  
  1461.         scol = (short)(j + xoff*COLS);
  1462.         srow = (short)(ROWS-1 + yoff*ROWS);
  1463.         my_setcolor(color);      /* MSC 6.0 */
  1464.         my_setpixel(scol, srow); /* MSC 6.0 */
  1465.  
  1466.       }        /* ends loop over j */
  1467.    }        /* ends if print == 0 */
  1468.  
  1469.  
  1470.    if(print == 1) print_halftone_array(in_image);
  1471.  
  1472. }  /*  ends half_tone  */
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.    /*******************************
  1479.    *
  1480.    *   get_threshold_value(...
  1481.    *
  1482.    ********************************/
  1483.  
  1484. get_threshold_value(threshold, print)
  1485.    int *print, *threshold;
  1486. {
  1487.    int i;
  1488.    printf("\nHT> The threshold = %d", *threshold);
  1489.    printf("\nHT> Enter new theshold value ");
  1490.    printf("(0 for no change) \n___\b\b\b");
  1491.    get_integer(&i);
  1492.    if((i != 0) && (i!= *threshold))
  1493.       *threshold = i;
  1494.  
  1495.    printf(
  1496.       "\nHT> print = %d (1 for print  0 for display)", 
  1497.       *print);
  1498.    printf("\nHT> Enter print value  \n_\b");
  1499.    get_integer(&i);
  1500.    *print = i;
  1501. }
  1502.  
  1503.  
  1504.  
  1505.  
  1506.    /********************************************
  1507.    *
  1508.    *   print_halftone_array(...
  1509.    *
  1510.    *   This function takes the halftoned images
  1511.    *   and prints it to a line printer.  If the
  1512.    *   image array has a 1 then print a ' '.
  1513.    *   If the image array has a 0 then print
  1514.    *   a '*'.
  1515.    *
  1516.    *********************************************/
  1517.  
  1518.  
  1519. print_halftone_array(image)
  1520.    short image[ROWS][COLS];
  1521. {
  1522.    char printer_name[80], response[80], string[101];
  1523.    FILE *printer;
  1524.    int        i, j, l, line_counter;
  1525.  
  1526.    line_counter = 0;
  1527.  
  1528.    strcpy(printer_name, "prn");
  1529.  
  1530.    if( (printer = fopen(printer_name, "w")) == NULL)
  1531.       printf("\nHT> Could not open printer");
  1532.    else{
  1533.       printf("\nOpened printer and now printing");
  1534.  
  1535.     /*************************************************
  1536.     *
  1537.     *   Loop over the rows in the image.  For each row
  1538.     *   first clear out the string print buffer.
  1539.     *   Then go through the columns and set the string
  1540.     *   to either '*' or ' '.  Finally, write the
  1541.     *   string out to the printer.
  1542.     *
  1543.     *************************************************/
  1544.  
  1545.    for(i=0; i<ROWS; i++){
  1546.  
  1547.       for(l=0; l<COLS+1; l++) string[l] = '\0';
  1548.  
  1549.       for(j=0; j<COLS; j++){
  1550.          if(image[i][j] == 1)
  1551.             string[j] = '*';
  1552.          else
  1553.             string[j] = ' ';
  1554.       }  /* ends loop over j columns */
  1555.  
  1556.       printf("%3d", i);
  1557.       fputs(string, printer);
  1558.       fputc('\n', printer);
  1559.       line_counter = line_counter + 1;
  1560.       if(line_counter >= 53){
  1561.          line_counter = 0;
  1562.          putc(FORMFEED, printer);
  1563.       }  /* ends if line_counter >=53  */
  1564.  
  1565.    }  /* ends loop over i rows */
  1566.  
  1567.  
  1568.    }  /* ends opened printer */
  1569.  
  1570.    putc(FORMFEED, printer);
  1571.    fclose(printer);
  1572.  
  1573. }  /* ends print_halftone_array */
  1574.